#include "EPubUtil.h"

EPUB_Size EPub_String_Split(const std::string &content, const std::string &delimiters, std::vector<std::string> &output)
{
	size_t last = 0;
	output.clear();

	for(std::string::size_type index = content.find_first_of(delimiters, last);
		index != std::string::npos;
		last = index + 1, index = content.find_first_of(delimiters, last))
	{
		output.push_back(content.substr(last, index - last));
	}

	if(last < content.length()) {
		output.push_back(content.substr(last));
	}

	return output.size();
}

EPUB_Size EPub_Xml_ParseAttribute(const std::string &pattern, std::map<std::string, std::string> &attrs)
{
	attrs.clear();

	std::vector<std::string> list;
	EPub_String_Split(pattern, ",", list);

	for(std::vector<std::string>::iterator iter = list.begin();
		iter != list.end();
		++iter)
	{
		std::vector<std::string> pair;
		if(EPub_String_Split((*iter), ":", pair) != 2) {
			continue;
		}

		attrs[pair[0]] = pair[1];
	}
	
	return attrs.size();
}

EPUB_Size EPub_Xml_ParseElement(const std::string &pattern, std::vector<std::string> &elems)
{
	EPub_String_Split(pattern, ">", elems);
	return elems.size();
}

bool EPub_Xml_Match_Attribute(const TiXmlElement *elem, const std::string &pattern)
{
	if(!elem) { return false; }
	if(pattern.empty()) { return true; }

	std::map<std::string, std::string> attrs;
	EPub_Xml_ParseAttribute(pattern, attrs);

	for(std::map<std::string, std::string>::iterator iter = attrs.begin();
		iter != attrs.end();
		++iter)
	{
		std::string temp_value;
		if(EPUB_FAILED(EPub_Xml_Attribute(elem, iter->first, temp_value))
		   || _strcmpi(temp_value.c_str(), iter->second.c_str()) != 0)
		{
			return false;
		}
	}

	return true;
}

EPUB_Result EPub_Xml_Attribute(const TiXmlElement *elem, const std::string &name, std::string &value)
{
	if(!elem) { return -1; }

	const char *temp = elem->Attribute(name.c_str());
	if(!temp) { return -1; }

	value = temp;
	return EPUB_SUCCESS;
}

EPUB_Result EPub_Xml_Attribute(const TiXmlElement *elem, const std::string &pattern, const std::string &name, std::string &value)
{
	if(!elem) { return -1; }

	if(pattern.empty()) {
		return EPub_Xml_Attribute(elem, name, value);
	}

	const TiXmlElement *temp_elem = NULL;
	EPUB_Result ret = EPUB_SUCCESS;

	ret = EPub_Xml_Element(elem, pattern, &temp_elem);

	if(EPUB_FAILED(ret)) {
		return ret;
	}

	return 0;

	//return EPub_Xml_Attribute(temp_elem, attr, out);
}

EPUB_Result EPub_Xml_Element(const TiXmlDocument *doc, const std::string &pattern_elem, const TiXmlElement **out)
{
	if(!doc || pattern_elem.empty()){
		return -1;
	}

	std::vector<std::string> elems;
	EPub_Xml_ParseElement(pattern_elem, elems);

	std::vector<std::string>::const_iterator iter = elems.begin();
	const TiXmlElement *ti_elem = doc->FirstChildElement(iter->c_str());

	while(iter != elems.end() && ti_elem) {
		++iter;
		if(iter == elems.end()) { break; }
		ti_elem = ti_elem->FirstChildElement(iter->c_str());
	}

	*out = ti_elem;
	return EPUB_SUCCESS;
}

EPUB_Result EPub_Xml_Element(const TiXmlElement *parent, const std::string &pattern_elem, const TiXmlElement **out)
{
	if(!parent || pattern_elem.empty()){
		return -1;
	}

	std::vector<std::string> elems;
	if(EPub_Xml_ParseElement(pattern_elem, elems) == 0) {
		return -1;
	}

	std::vector<std::string>::const_iterator iter = elems.begin();
	const TiXmlElement *ti_elem = parent->FirstChildElement(iter->c_str());

	while(iter != elems.end() && ti_elem) {
		++iter;
		if(iter == elems.end()) { break; }
		ti_elem = ti_elem->FirstChildElement(iter->c_str());
	}

	*out = ti_elem;
	return EPUB_SUCCESS;
}

EPUB_Result EPub_Xml_Element(const TiXmlElement *parent, const std::string &pattern_elem, const std::string &pattern_attr, const TiXmlElement **out)
{
	if(!parent || pattern_elem.empty()){
		return -1;
	}

	if(pattern_attr.empty()) {
		return EPub_Xml_Element(parent, pattern_elem, out);
	}

	const TiXmlElement * ti_elem = NULL;
	EPub_Xml_Element(parent, pattern_elem, &ti_elem);

	while(ti_elem && !EPub_Xml_Match_Attribute(ti_elem, pattern_attr)) {
		ti_elem = ti_elem->NextSiblingElement(ti_elem->Value());
	}

	if(!ti_elem) {
		return -1;
	}

	*out = ti_elem;
	return EPUB_SUCCESS;
}

EPUB_Result EPub_Xml_Text(const TiXmlElement *elem, std::string &out)
{
	if(!elem) { return -1; }

	const char *temp = elem->GetText();
	if(!temp) {
		return -1;
	}

	out = temp;
	return EPUB_SUCCESS;
}

EPUB_Result EPub_Xml_Text(const TiXmlElement *elem, const std::string &pattern_elem, std::string &out)
{
	if(!elem) { return -1; }

	if(pattern_elem.empty()) {
		return EPub_Xml_Text(elem, out);
	}

	const TiXmlElement *temp_elem = NULL;
	EPUB_Result ret = EPUB_SUCCESS;

	ret = EPub_Xml_Element(elem, pattern_elem, &temp_elem);
	if(EPUB_FAILED(ret)) { return ret; }

	return EPub_Xml_Text(temp_elem, out);
}